#import "AppDelegate.h"
#import "AppViewController.h"
#import "FontManager.h"
#import <mach/mach.h>
#import <mach/mach_host.h>

@implementation AppDelegate {
    
}

@synthesize window = window_, navController = navController_;

- (void) mainLoop
{
//    // Check memory every a loop time
//    if (CFAbsoluteTimeGetCurrent() - _checkingMemoryTimer > TIMER_CHECKING_MEMORY) {
//        _checkingMemoryTimer = CFAbsoluteTimeGetCurrent();
//
//        struct task_basic_info info;
//        mach_msg_type_number_t size = sizeof(info);
//        kern_return_t kerr = task_info(mach_task_self(),
//                                       TASK_BASIC_INFO,
//                                       (task_info_t)&info,
//                                       &size);
//        if( kerr == KERN_SUCCESS ) {
//            NSLog(@"Memory in use (in megabytes): %u", info.resident_size /1048576);
//        } else {
//            NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
//        }
//    }
    
    [[AppViewController Shared] update];
}

- (void)loadFontManager {
    [[FontManager sharedManager] loadFont:@"Bebas Neue"];
    [[FontManager sharedManager] loadFont:@"Comfortaa-Thin"];
    [[FontManager sharedManager] loadFont:@"Comfortaa-Bold"];
    [[FontManager sharedManager] loadFont:@"Comfortaa-Regular"];
    [[FontManager sharedManager] loadFont:@"Kristen ITC"];
    [[FontManager sharedManager] loadFont:@"UVN But Long 2"];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    navController_ = [[UINavigationController alloc] initWithRootViewController:[AppViewController Shared]];
    navController_.view.backgroundColor = [UIColor blackColor];
    navController_.navigationBar.backgroundColor = [UIColor blackColor];
    
    [navController_ setNavigationBarHidden:YES];
    window_.rootViewController = navController_;
    
    application.applicationSupportsShakeToEdit = YES;
    application.statusBarHidden = YES;
    [[AppViewController Shared] changeToSplashScreen];
    
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
    
    _timerMain = [NSTimer scheduledTimerWithTimeInterval:TIMER_MAIN_LOOP target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:_timerMain forMode:NSRunLoopCommonModes];
    
#ifdef __FREE__
    
#define STRING_PUZZLE_GAME_RATING_TITLE                                 @"Thank you!\nThis Is Free Version. Please help us rate it!"
#define STRING_PUZZLE_GAME_RATING_RATE_IT_NOW                           @"Rate It Now"
#define STRING_PUZZLE_GAME_RATING_REMIND_ME_LATER                       @"Remind Me Later"
#define STRING_PUZZLE_GAME_RATING_NO_THANKS                             @"No, Thanks"
#define STRING_PUZZLE_GAME_RATING_BUNDLE_ID                             @"com.kidbaw.phongdep"
    
    NSString *bundleIDString = STRING_PUZZLE_GAME_RATING_BUNDLE_ID;
    
    // iRate
//    [iRate sharedInstance].applicationBundleID = [[NSBundle mainBundle] bundleIdentifier];
    [iRate sharedInstance].applicationBundleID = bundleIDString;
    [iRate sharedInstance].delegate = self;
    [iRate sharedInstance].messageTitle = STRING_PUZZLE_GAME_RATING_TITLE;
    [iRate sharedInstance].rateButtonLabel = STRING_PUZZLE_GAME_RATING_RATE_IT_NOW;
    [iRate sharedInstance].remindButtonLabel = STRING_PUZZLE_GAME_RATING_REMIND_ME_LATER;
    [iRate sharedInstance].cancelButtonLabel = STRING_PUZZLE_GAME_RATING_NO_THANKS;
    [iRate sharedInstance].message = @"";
	[iRate sharedInstance].onlyPromptIfLatestVersion = NO;
    
#else
#endif
    
    [window_ makeKeyAndVisible];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    
    NSLog(@"applicationWillResignActive");
    UIApplication *app = [UIApplication sharedApplication];
    
    // Request permission to run in the background. Provide an
    // expiration handler in case the task runs long.
    NSAssert(_bgTask == UIBackgroundTaskInvalid, nil);
    
    _bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        // Synchronize the cleanup call on the main thread in case
        // the task actually finishes at around the same time.
        dispatch_async(dispatch_get_main_queue(), ^{
            
            if (_bgTask != UIBackgroundTaskInvalid)
            {
                [app endBackgroundTask:_bgTask];
                _bgTask = UIBackgroundTaskInvalid;
            }
        });
    }];
    
    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        // Do the work associated with the task.
        
        // Turn On/Off Location Service
//        [[AutomationDataManager Shared] stopUpdateLocationService];
//        [[AutomationDataManager Shared] startMonitoringSignificantLocationChanges];
        
        //        NSLog(@"App staus: applicationDidEnterBackground");
        // Synchronize the cleanup call on the main thread in case
        // the expiration handler is fired at the same time.
        dispatch_async(dispatch_get_main_queue(), ^{
            if (_bgTask != UIBackgroundTaskInvalid)
            {
                [app endBackgroundTask:_bgTask];
                _bgTask = UIBackgroundTaskInvalid;
            }
        });
    });
    
//    NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);
    
    // UPDATTE USER ID AND DEVICE TOKEN
    [[AppViewController Shared] requestUpdateUserID_Or_DeviceUDID_Or_DeviceToken];
}



- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    NSLog(@"applicationDidBecomeActive");
    
    // Turn On/Off Location Service
//    [[AutomationDataManager Shared] stopMonitoringSignificantLocationChanges];
//    [[AutomationDataManager Shared] startUpdateLocationService];
    
//    // LOCATION SERVICE
//    [[AutomationDataManager Shared] startUpdateLocationService];
    
    // UPDATTE USER ID AND DEVICE TOKEN
    [[AppViewController Shared] requestUpdateUserID_Or_DeviceUDID_Or_DeviceToken];
}

- (void)scheduleAlarmForDate:(NSDate*)theDate
{
    UIApplication* app = [UIApplication sharedApplication];
    NSArray*    oldNotifications = [app scheduledLocalNotifications];
    
    // Clear out the old notification before scheduling a new one.
    if ([oldNotifications count] > 0)
        [app cancelAllLocalNotifications];
    
    // Create a new notification.
    UILocalNotification* alarm = [UILocalNotification new];
    if (alarm)
    {
        alarm.fireDate = theDate;
        alarm.timeZone = [NSTimeZone defaultTimeZone];
        alarm.repeatInterval = 0;
        alarm.soundName = UILocalNotificationDefaultSoundName;
        alarm.alertBody = @"Countdown Time is over.";
        
        [app scheduleLocalNotification:alarm];
    }
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
     */
    NSLog(@"applicationDidEnterBackground");
    if (_timerMain) {
        [_timerMain invalidate];
        _timerMain = [NSTimer scheduledTimerWithTimeInterval:TIMER_MAIN_LOOP_BACKGROUND target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
    }
    
    // Timer Count Down
    [AppViewController Shared].backgroundTimeInterval = CFAbsoluteTimeGetCurrent();
    NSTimeInterval remainingTime = [AppViewController Shared].remainingTime;
    if (remainingTime > 0) {
        NSDate *remainingDate = [NSDate dateWithTimeIntervalSinceNow:remainingTime];
        [self scheduleAlarmForDate:remainingDate];
        
    }
    
    [[AppViewController Shared] applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    /*
     Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
     */
    NSLog(@"applicationWillEnterForeground");
    if (_timerMain) {
        [_timerMain invalidate];
        _timerMain = [NSTimer scheduledTimerWithTimeInterval:TIMER_MAIN_LOOP target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:_timerMain forMode:NSRunLoopCommonModes];
    }
    
    // Timer Count Down
    NSTimeInterval temp = CFAbsoluteTimeGetCurrent() - [AppViewController Shared].backgroundTimeInterval;
    NSTimeInterval remainingTime = [AppViewController Shared].remainingTime;
    if ((remainingTime - temp) > 0) {
        [AppViewController Shared].remainingTime -= temp;
    } else {
        [AppViewController Shared].remainingTime = 0;
    }
    
    [[AppViewController Shared] applicationWillEnterForeground:application];
}


- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    NSLog(@"applicationWillTerminate");
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *newDeviceToken = [deviceToken description];
    newDeviceToken = [newDeviceToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    newDeviceToken = [newDeviceToken stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", newDeviceToken);
    
    // UPDATE USER ID AND DEVICE TOKEN
    [UserDataManager Shared].userRegisteredDeviceToken = newDeviceToken;
    [[UserDataManager Shared] save];
    [[AppViewController Shared] requestUpdateUserID_Or_DeviceUDID_Or_DeviceToken];
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
    NSLog(@"didFailToRegisterForRemoteNotificationsWithError: error = %@", err);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"didReceiveRemoteNotification: %@", userInfo);
//    enumRemoveNotificationType notificationType = [[userInfo valueForKey:@"type"] integerValue];
//    
//    [[AppViewController Shared] didReceiveRemoteNotification:userInfo andNotificationType:notificationType];
    
    NSString *alertMessage = [[userInfo objectForKey:STRING_RESPONSE_KEY_APS] objectForKey:STRING_RESPONSE_KEY_ALERT];
    NSLog(@"%@", alertMessage);
//    enumRemoveNotificationType notificationType = [[userInfo objectForKey:STRING_RESPONSE_KEY_NOTIFICATION_TYPE] integerValue];
    
    if (application.applicationState == UIApplicationStateActive) {
        NSLog(@"UIApplicationStateActive");
        
        [[AppViewController Shared] showNotificationWithMessage:alertMessage andIsShowed:YES];
    }
    else if (application.applicationState == UIApplicationStateInactive) {
        NSLog(@"UIApplicationStateInactive");
    }
    else if (application.applicationState == UIApplicationStateBackground) {
        NSLog(@"UIApplicationStateBackground");
    }
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
#ifdef __DEBUG__
//    NSLog(@"didReceiveLocalNotification: %@", notification);
    NSLog(@"didReceiveLocalNotification");
#endif
}

@end
